//============================================================================================
/**
 * @file	ev_check.c
 * @brief	イベント発動チェックシステム
 * @author	Sousuke Tamada
 * @date	01.03.29
 *
 * 05.07.04 Hiroyuki Nakamura
 */
//============================================================================================

// この定義を有効にすると環境音に関する処理を行わなくなる
// データ無視、再生処理等に行かなくなります
// 金銀セーブデータ復旧用に作成
//#define NO_FIELD_SE


#include "common.h"

#include "system/snd_tool.h"
#include "system/snd_play.h"
#include "system/bmp_menu.h"
#include "system/bmp_list.h"
#include "system/clact_tool.h"
#include "system/wipe.h"
#include "system/wipe_def.h"
#include "fieldsys.h"
#include "field_clact.h"
#include "fld_menu.h"
#include "sxy.h"
#include "script.h"
#include "map_tool.h"

#define EV_CHECK_H_GLOBAL
#include "ev_check.h"
#include "eventdata.h"		//ゾーン毎のイベントデータ参照のため

#include "fld_debug.h"

#include "field_event.h"
#include "field_encount.h"
#include "player_event_arrowmat.h"

#include "ev_mapchange.h"

#include "script.h"
#include "zonedata.h"
#include "mapdefine.h"
#include "poketool/pokeparty.h"

#include "fieldobj.h"

#include "ev_trainer.h"
#include "communication/wh_config.h"
#include "communication/wh.h"
#include "communication/communication.h"
#include "communication/comm_state.h"
#include "comm_command_field.h"
#include "comm_direct_counter.h"
#include "comm_field_state.h"
#include "comm_vsroom.h"
#include "comm_player.h"
//#include "underground/ug_manager.h"

#include "map_attr.h"
#include "ev_pokemon.h"		//EvPoke_Enable2vs2Battle

#include "field\eventflag.h"

#include "..\fielddata\script\common_scr_def.h"
#include "..\fielddata\script\hiden_def.h"
#include "..\fielddata\script\bg_attr_def.h"
#include "..\fielddata\script\safari_def.h"
#include "..\fielddata\script\mushitori_def.h"
#include "..\fielddata\script\battle_room_def.h"
#include "..\fielddata\script\tv_def.h"
#include "../fielddata/script/union_def.h"

#define	SCRID_COMMON_MSG	0

#include "field_3d_anime_ev.h"

#include "map_jump_def.h"
#include "map_jump.h"

#include "situation_local.h"

#include "savedata/savedata.h"
#include "savedata/zukanwork.h"
#include "savedata/sodateyadata.h"
#include "savedata/record.h"
#include "savedata/pgear_sv_util.h"
#include "sodateya.h"

#include "syswork.h"
#include "sysflag.h"

#include "gym.h"
#include "poison_effect.h"
#include "fieldmap_work.h"

#include "battle\wazano_def.h"
#include "comm_union_beacon.h"

#include "btl_searcher.h"

#include "system/debug_flag.h"
#include "field/field_se.h"

#include "spray.h"
#include "pokepark_sys.h"
#include "field_poketch.h"

#include "pair_poke_humor.h"
#include "fld_pmtel.h"
#include "fld_safari.h"
#include "gym_init.h"
#include "field_gimmick_def.h"
#include "fld_mushitori.h"

#include "field/evwkdef.h"
#include "sysflag.h"

#include "sheimi_form_rev.h"	//for SheimiFrmRev_CheckForm

#include "field/field_se.h"

//#define	DEBUG_ALL_EXIT_CONNECT
//============================================================================================
//	定数定義
//============================================================================================
#define	ALL_KEY		( PAD_KEY_UP | PAD_KEY_DOWN | PAD_KEY_LEFT | PAD_KEY_RIGHT )

#define	PAD_BUTTON_MENU		( PAD_BUTTON_X )		// メニューボタン
#define	PAD_BUTTON_BENRI	( PAD_BUTTON_Y )		// 便利ボタン


///毒ダメージを受ける歩数
#define	POISON_STEP_MAX		(4)

///なつき度計算する歩数
#define FRIENDCALC_STEP_MAX	(128)


///< フィールドSE再生ではない状態
#define FIELD_SE_NONE_NO	( -1 )

///< フィールド効果音のボリューム定義の最大数
#define FIELD_SE_VOLUME_MAX	(  3 )

#define	ENC_WALK_CNT_MAX	(0xffff)

#ifdef PM_DEBUG
//有効でバトルレコーダー安全フラグオンセーブ起動デバッグ処理
//#define AFTERMASTER_BTL_REC_FORCE_SVAE
#endif

#ifdef AFTERMASTER_BTL_REC_FORCE_SVAE

#include "savedata/battle_rec.h"

#include "savedata/gds_local_common.h"
#include "savedata/gds_profile_types.h"
#include "savedata/mystatus_local.h"
#include "savedata/battle_rec_local.h"
#include "report.h"

extern BATTLE_REC_SAVEDATA * brs;
static void DBG_BattleRec_SecureFlagSet(SAVEDATA *sv);
///static SAVE_RESULT DBG_save(SAVEDATA *sv, int num);
static SAVE_RESULT DBG_BattleRec_Save(SAVEDATA *sv, int num, u16 *work0, u16 *work1);
static SAVE_RESULT DBG_Local_BattleRecSave(SAVEDATA *sv, BATTLE_REC_SAVEDATA *work, int num, u16 *seq);
#endif  //AFTERMASTER_BTL_REC_FORCE_SVAE


//============================================================================================
//	構造体定義
//============================================================================================

///< フィールド効果音テーブル定義
typedef struct{
	u8 se,vol;		// SE・音量
	u8 etc1,etc2;	// 未使用
	u8 x1,y1;		// 左上座標XY（ツールで必ず左上が約束されている）
	u8 x2,y2;		// 右下座標XY（ツールで必ず右下が約束されている）
}FIELD_SE;

typedef struct{
	u16 		signature;	///< 必ず「0x1234」
	u16 		size;		///< 後ろに続くSE領域情報のバイト数（これを8で割れば領域の数）
	FIELD_SE 	setable[0]; ///< フィールドSE領域の配列
}FIELD_SE_TABLE;

//============================================================================================
//
//
//
//============================================================================================
static BOOL EvCheck_ExitByPush(FIELDSYS_WORK * fsys, const EV_REQUEST * req);
static  u16 EvCheck_TalkMapAttr(FIELDSYS_WORK * repw, MATR matr);

static BOOL CheckEncountEvent(FIELDSYS_WORK * fsys);
static BOOL CheckMoveEvent(FIELDSYS_WORK * fsys);// 一歩ごとのイベント起動チェック
static BOOL CheckPosEvent(FIELDSYS_WORK * fsys);
static BOOL CheckExit(FIELDSYS_WORK * fsys, const int x, const int z, const u8 inAttr);
static BOOL CheckSodateya( FIELDSYS_WORK *fsys );
static BOOL CheckPoison(FIELDSYS_WORK * fsys);
static BOOL CheckSafariStep(FIELDSYS_WORK * fsys);
static BOOL CheckBoardStart( FIELDSYS_WORK * repw );
static BOOL CheckSpray( FIELDSYS_WORK *fsys );
static BOOL CheckMushitoriTime(FIELDSYS_WORK * fsys);
static void CheckBongJuiceStep(FIELDSYS_WORK * fsys);

static BOOL CheckFriendCalcStepCount( FIELDSYS_WORK *fsys );
static void DoFriendCalcStepCount( FIELDSYS_WORK *fsys );
static BOOL CheckTelEvent(FIELDSYS_WORK * fsys);



//ツール関数
static void GetNowPos(const FIELDSYS_WORK * fsys, int *x, int *z);
static void GetFrontPos(const FIELDSYS_WORK * fsys, int * x, int * z);
static void GetMovePos(const FIELDSYS_WORK * fsys, int dir, int * x, int * z);
static u8 GetNowAttr(const FIELDSYS_WORK * fsys);
static u8 GetFrontAttr(const FIELDSYS_WORK * fsys);
static u8 GetFrontHitAttr(const FIELDSYS_WORK * fsys);

static BOOL GetConnectData(const FIELDSYS_WORK * fsys, int x, int z, LOCATION_WORK * next);

static void SetEscapeData(FIELDSYS_WORK * fsys);
static void FieldSeFunc( FIELDSYS_WORK *fsys, const int x, const int y );
static int FieldSeAttrHitCheck( const FIELD_SE_TABLE *fst, const int x, const int y );
static int FieldSe_CheckCancel( FIELDSYS_WORK *fsys, FIELD_SE_TABLE *fld_se_table, const int seattr );

static u16 CheckTreeOutRange(FIELDSYS_WORK * repw);

#ifdef PM_DEBUG
extern BOOL Debug_SetPokeChgEvent(FIELDSYS_WORK * fsys, int trg);
extern void DebugPrintStress(void);
#endif

static void Request_CnvButton( FIELDSYS_WORK* repw, const u16 ReqCnvButton );


#ifdef AFTERMASTER_BTL_REC_FORCE_SVAE
static void DBG_CreateBtlRecSvEvt(FIELDSYS_WORK * fsys);
static BOOL BtlRecSvEvt(GMEVENT_CONTROL * event);
#endif  //AFTERMASTER_BTL_REC_FORCE_SVAE

//============================================================================================
//============================================================================================
//--------------------------------------------------------------------------------------------
/**
 * イベントチェックリクエストの初期化
 *
 * @param	req		イベントチェックリクエスト構造体
 *
 * @return	none
 */
//--------------------------------------------------------------------------------------------
static void ClearRequest( EV_REQUEST * req )
{
	req->TalkCheck  = FALSE;
	req->StepCheck  = FALSE;
	req->MenuOpen   = FALSE;
	req->CnvButton  = FALSE;
	req->MatCheck   = FALSE;
	req->PushCheck  = FALSE;
	req->MoveCheck  = FALSE;
	req->TelCheck = FALSE;
	req->DowsingEnd = FALSE;

	req->DebugMenu   = FALSE;
	req->DebugBattle = FALSE;

	req->DebugHook     = FALSE;
	req->DebugKeyPush  = FALSE;

	req->Site = DIR_NOT;
	req->PushSite = DIR_NOT;
}

//--------------------------------------------------------------------------------------------
/**
 * サブ画面が完全に切り替わっているか
 *
 * @param	fsys	FIELDSYS_WORK
 *
 * @retval	"TRUE = 切り替わっている"
 * @retval	"FALSE = それ以外"
 */
//--------------------------------------------------------------------------------------------
static BOOL SubLcdFieldMenuCheck( FIELDSYS_WORK * fsys )
{
//	if( FieldSubLcdControler_GetNowApp(fsys) == SUBLCD_MODE_FIELD_MENU &&
//		FieldSubLcdControler_GetSequence(fsys) == SUBLCD_SEQ_MAIN ){
	if( FieldSubLcdControler_GetSequence(fsys) == SUBLCD_SEQ_MAIN ){
		return TRUE;
	}
	return FALSE;
}


//-----------------------------------------------------------------------------
/**
 *	@brief	便利ボタンの起動リクエスト
 *
 *	@param	FIELDSYS_WORK* repw
 *	@param	u16 ReqCnvButton
 *
 *	@retval	none
 */
//-----------------------------------------------------------------------------
static void Request_CnvButton( FIELDSYS_WORK* repw, const u16 ReqCnvButton )
{
	// before_poketch.c に通知
	FieldSubLcdControler_FieldMenuShortcutFlagSet( repw, ReqCnvButton );
}


//--------------------------------------------------------------------------------------------
/**
 * イベントチェックリクエストのセット
 *
 * @param	req		イベントチェックリクエスト構造体
 * @param	trg		キートリガー情報
 * @param	cont	キー押し情報
 *
 * @return	none
 */
//--------------------------------------------------------------------------------------------
void SetRequest( EV_REQUEST * req, FIELDSYS_WORK * repw, u16 trg, u16 cont )
{

	int	st;
	int	val;
	int dir;
	BOOL b_bag_get_flag;

	ClearRequest(req);

	// 09.05.01 ここでシューズボタンによるダッシュをシミュレートする add by hosaka genya
	{
		u16 key_prs;
		PLAYER_STATE_PTR jiki;

		jiki = Player_FieldSysWorkPlayerGet( repw );

		if( Player_DashBitGet(jiki) ){
			cont |= PAD_BUTTON_B;
		}
	}

	st  = Player_MoveStateGet( repw->player );		// 自機の状態
	val = Player_MoveValueGet( repw->player );		// 自機の移動状態
	dir = Player_DirGet( repw->player );			// 自機の方向
	req->trg = trg;
	req->cont = cont;

	// バッグ入手フラグ
	b_bag_get_flag = FldMenu_ExecuteCheck( repw, FLD_APPEAR_BAG );

	if( st == OBJ_MOVE_STATE_END || st == OBJ_MOVE_STATE_OFF ) {
		// ショートカット処理（バッグがないと作動しない）
		if( ( b_bag_get_flag && (trg & PAD_BUTTON_BENRI ) ) ||
			repw->sub_panel_trg == SUBLCD_TOUCH_SHORTCUT1 ) {
			if( SubLcdFieldMenuCheck( repw ) == TRUE ) {
				req->CnvButton = 1;
				repw->sub_panel_trg = SUBLCD_TOUCH_NONE;
				OS_Printf("CnvButton = %d\n", req->CnvButton);
			}
		} else if( repw->sub_panel_trg == SUBLCD_TOUCH_SHORTCUT2 ) {
			if( SubLcdFieldMenuCheck( repw ) == TRUE ) {
				req->CnvButton = 2;
				repw->sub_panel_trg = SUBLCD_TOUCH_NONE;
				OS_Printf("CnvButton = %d\n", req->CnvButton);
			}
		} else if( repw->sub_panel_trg == SUBLCD_TOUCH_DOWSING_END ) {
			// ダウジングマシン終了(タッチ操作)
			req->DowsingEnd = TRUE;
			repw->sub_panel_trg = SUBLCD_TOUCH_NONE;
		} else if( (trg & PAD_BUTTON_MENU)  || repw->sub_panel_trg != SUBLCD_TOUCH_NONE ) {
			if( FieldSubLcdControler_GetNowApp( repw ) == SUBLCD_MODE_DOWSING_MENU ) {
				// ダウジングマシン終了( ボタン操作 )
				KeyTouchStatus_SetTouchOrKey( &repw->KeyTouchStatus, APP_END_KEY );
				req->DowsingEnd = TRUE;
				req->MenuOpen = TRUE;
			} else
				if( b_bag_get_flag ) {
				// メニューを開く処理（バッグがあるときのみ
				req->MenuOpen = TRUE;

				if( repw->sub_panel_trg == SUBLCD_TOUCH_OPEN_MENU ) {
					OS_TPrintf("sub_panel_trg = %d\n", repw->sub_panel_trg);
					repw->sub_panel_trg = SUBLCD_TOUCH_NONE;
				}
			}
		} else if( trg & PAD_BUTTON_DECIDE ) {
			// 会話進行
			req->TalkCheck = TRUE;
		}

		if( cont & ALL_KEY ) {
			req->MatCheck = TRUE;
			req->PushCheck = TRUE;
		}
		//電話着信チェックをしていい
		req->TelCheck = TRUE;
	} else {
		// キーが入力できない状態のときは、タッチ情報をリセット
		repw->sub_panel_trg = SUBLCD_TOUCH_NONE;
	}

	if( st == OBJ_MOVE_STATE_END && val == OBJ_MOVE_VALUE_WALK ){
		req->MoveCheck = TRUE;
	}

	// 一歩移動終了タイミングか？
	if (st == OBJ_MOVE_STATE_END) {
		req->StepCheck = TRUE;
	}

	if ((dir == DIR_UP && (cont & PAD_KEY_UP))
			|| ((dir == DIR_DOWN) && (cont & PAD_KEY_DOWN))
			|| ((dir == DIR_LEFT) && (cont & PAD_KEY_LEFT))
			|| ((dir == DIR_RIGHT) && (cont & PAD_KEY_RIGHT))
	   ) {
		req->PushSite = dir;
	} else {
		req->PushSite = DIR_NOT;
	}

//上下優先のとり方から自機独自のキー入力関数に変更 060317 kaga
#if 0
	// 移動方向のリクエスト
	if( cont & PAD_KEY_UP ){
		req->Site = DIR_UP;
	}else if( cont & PAD_KEY_DOWN ){
		req->Site = DIR_DOWN;
	}else if( cont & PAD_KEY_LEFT ){
		req->Site = DIR_LEFT;
	}else if( cont & PAD_KEY_RIGHT ){
		req->Site = DIR_RIGHT;
	}
#else
	req->Site = Player_KeyDirGet( repw->player, trg, cont );
#endif

	// 以下はデバッグ機能の発動チェック
#ifdef	PM_DEBUG
	if( cont & PAD_BUTTON_R ){
		req->DebugKeyPush = TRUE;

		//Rボタンを押しているときは各種イベントの発動を抑える
		req->MoveCheck = FALSE;
		req->StepCheck = FALSE;
		req->MatCheck = FALSE;
		req->PushCheck = FALSE;
		req->TelCheck = FALSE;

		if( req->MenuOpen ){
			req->MenuOpen = FALSE;
			req->DebugMenu = TRUE;
		}
	}

/*
	if( st == OBJ_MOVE_STATE_END || st == OBJ_MOVE_STATE_OFF ){
		if( cont & PAD_BUTTON_R ){
			// デバッグバトル
			if( (cont & PAD_BUTTON_START) && !(req->DebugMenu) ){
				req->DebugBattle = TRUE;
			}
		}
	}
*/
#endif	// PM_DEBUG

}

//--------------------------------------------------------------------------------------------
/**
 * イベント起動チェック
 *
 * @param	req		イベントチェックリクエスト
 *
 * @retval	"TRUE = イベント発動"
 * @retval	"FALSE = イベント発動なし"
 *
 *	リクエストを元にチェックプログラムを呼び出し、イベントを起動する
 */
//--------------------------------------------------------------------------------------------
int CheckRequest(const EV_REQUEST * req, FIELDSYS_WORK * repw)
{
#ifdef AFTERMASTER_BTL_REC_FORCE_SVAE
  if ( (sys.cont & PAD_BUTTON_SELECT) ){
    if (sys.trg & PAD_BUTTON_A){
      //イベント作成
      DBG_CreateBtlRecSvEvt(repw);
      return CHECK_REQUEST_RETCODE_NORMAL;
    }
  }
#endif //AFTERMASTER_BTL_REC_FORCE_SVAE
	//特殊スクリプト（シーン起動スクリプト）チェック
	if (req->DebugKeyPush == FALSE && SpScriptSearch(repw, SP_SCRID_SCENE_CHANGE) == TRUE) {
		return CHECK_REQUEST_RETCODE_NORMAL;
	}

	//トレーナー視線チェック
	{
		if( req->DebugKeyPush == FALSE ){
			BOOL flag = EvPoke_Enable2vs2Battle(SaveData_GetTemotiPokemon(repw->savedata));

			if( SysFlag_PairCheck(SaveData_GetEventWork(repw->savedata)) == 1 ){
				flag = TRUE;		//連れ歩き中ならダブル可能
			}

			if( EvTrainerEyeCheck(repw,flag) == TRUE ){
				Player_MoveStateClear( repw->player );
				FieldOBJSys_MovePauseAll( repw->fldobjsys );
				if (PairPoke_IsPairPoke(repw)){
					//連れ歩きポケモンポーズ解除
					FieldOBJ_MovePauseClear( PairPoke_GetFldObjPtr(repw) );
				}
				return CHECK_REQUEST_RETCODE_NORMAL;
			}
		}
	}


	//一歩移動チェック
	if (req->MoveCheck) {
		//一歩動いたかどうかフラグの更新
		SysFlag_OneStepReset( SaveData_GetEventWork(repw->savedata) );
		//IncRecord( CNT_WALK );
		if( CheckMoveEvent( repw ) == TRUE ){
			return CHECK_REQUEST_RETCODE_NORMAL;
		}
	}
	//虫取り大会経過時間チェック
	if(CheckMushitoriTime(repw)){
		return CHECK_REQUEST_RETCODE_NORMAL;
	}
	//自機イベントチェック
	{
		HERO_EVBIT evbit = HERO_EVBIT_NON;
		int dir = Player_KeyDirGet( repw->player, req->trg, req->cont );

		if (SysFlag_KairikiCheck( SaveData_GetEventWork(repw->savedata) )) {
			evbit |= HERO_EVBIT_PERMIT_KAIRIKI;
		}

		if( EvPoke_CheckWaza(SaveData_GetTemotiPokemon(repw->savedata),
					WAZANO_TAKINOBORI) != 0xff) {
			evbit |= HERO_EVBIT_PREMIT_TAKINOBORI;
		}

		if( Player_EventMoveCheck(repw,repw->player,dir,evbit) == TRUE ){
			return CHECK_REQUEST_RETCODE_NORMAL;
		}
	}

	//自機動作チェック（一歩移動 あるいは 振り向き）
	if(req->StepCheck ){
		// エンカウント
		if (CheckEncountEvent(repw)) {
			return CHECK_REQUEST_RETCODE_NORMAL;
		}


		// 看板チェック
		if( CheckBoardStart(repw) == TRUE ){
			return CHECK_REQUEST_RETCODE_NORMAL;
		}
	}

	//方向転換でうまく動作しないので、ここでも看板チェック ( FR/LG のマネ )
	if( req->MatCheck && Player_DirGet(repw->player) == req->Site ){
		// 看板チェック
		if( CheckBoardStart(repw) == TRUE ){
			return CHECK_REQUEST_RETCODE_NORMAL;
		}
	}

	// 会話
	if( req->TalkCheck ){

		{	// OBJとの会話チェック
			FIELD_OBJ_PTR obj;
			if( TalkObjEventCheck( repw, &obj ) == TRUE ){

				if( Player_MoveForceStopCheck( repw->player ) == TRUE ){
					Player_MoveForceStop( repw->player, Player_DirGet(repw->player) );
				}
				if (FieldOBJ_EventTypeGet(obj) != EV_TYPE_MSG) {
					EventSet_Script( repw, FieldOBJ_EventIDGet(obj), obj );
				} else {
					EventSet_Script( repw, SCRID_COMMON_MSG, obj );
				}
				repw->sub_panel_trg = SUBLCD_TOUCH_NONE;
				return CHECK_REQUEST_RETCODE_NORMAL;
			}
		}

		{	// BGの話しかけチェック
			int	id;

			id = TalkBgEventCheck(
					repw,
					(void *)EventData_GetNowBgTalkData( repw ),
					EventData_GetNowBgTalkDataSize( repw ) );

			if( id != EVENT_ID_NONE ){
				EventSet_Script( repw, id, NULL );
				repw->sub_panel_trg = SUBLCD_TOUCH_NONE;
				return CHECK_REQUEST_RETCODE_NORMAL;
			}
		}

		{
			int id;
			id = EvCheck_TalkMapAttr(repw, GetFrontAttr(repw));
			if (id != EVENT_ID_NONE) {
				EventSet_Script(repw, id, NULL);
				repw->sub_panel_trg = SUBLCD_TOUCH_NONE;
				return CHECK_REQUEST_RETCODE_NORMAL;
			}

		}

		{	//範囲外話しかけ（頭突き用）
			int id;
			id = CheckTreeOutRange(repw);
			if (id != EVENT_ID_NONE) {
				EventSet_Script(repw, id, NULL);
				repw->sub_panel_trg = SUBLCD_TOUCH_NONE;
				return CHECK_REQUEST_RETCODE_NORMAL;
			}
		}
	}

#ifdef PM_DEBUG
	{
		if (sys.trg & PAD_BUTTON_DEBUG){
			DebugPrintStress();
		}
	}
#endif

#ifdef DEBUG_ONLY_FOR_saitou
	//イベントテスト

	{
/**
		if( sys.trg & PAD_BUTTON_START ){
			//シームレスカメラ
			//SMLS_CamCnt_Request(repw->SmlsCamCntPtr, 1);
			//return TRUE;
			sys_PrintHeapFreeSize( HEAPID_BASE_APP );
			sys_PrintHeapFreeSize( HEAPID_FIELD_FLDOBJ_MDL );
			BongSys_Growth(repw);
			if (GYM_GimmickCodeCheck(repw, FLD_GIMMICK_COMBAT_GYM)){
				GYM_CheckCombatGymEvt(repw);
			}
			return TRUE;
		}

		if (sys.trg & PAD_BUTTON_SELECT){
			debug_auto_move = (debug_auto_move+1)%2;
		}
*/
	}
#endif	// DEBUG_ONLY_FOR_saitou

	if (req->PushCheck) {
		if (EvCheck_ExitByPush(repw, req) == TRUE) {
			SetEscapeData(repw);
			return CHECK_REQUEST_RETCODE_NORMAL;
		}
	}

	// 以下は、主人公の位置が無関係なイベント
	//

	// 便利ボタンチェック
	if( req->CnvButton ) {
		int ret = FieldConvButtonEventInit( repw, req->CnvButton );
		if( ret != CHECK_REQUEST_RETCODE_NULL ) {
			Request_CnvButton( repw, req->CnvButton );
			return ret;
		}
	}

	// メニューチェック
	if( req->MenuOpen ){
		if( FieldMenuCallCheck( repw ) == TRUE ){	// 「なぞのばしょ」チェック 2006/10/24 by nakahiro
			Snd_SePlay( SE_WIN_OPEN );
		    FieldMenuInit( repw );
			return CHECK_REQUEST_RETCODE_TEL;
//			return CHECK_REQUEST_RETCODE_NORMAL;
		}
	}
#ifdef	PM_DEBUG
	// 戦闘テストへ
	if( req->DebugBattle ){
		DebugFieldEncount( repw );	//無条件でエンカウントセット
		return CHECK_REQUEST_RETCODE_NORMAL;
	}

	if( req->DebugMenu ){
		Snd_SePlay( SE_WIN_OPEN );
		FieldDebugListSet( repw );
		return CHECK_REQUEST_RETCODE_NORMAL;
	}

	//連れ歩きデバッグイベント
	if ( Debug_SetPokeChgEvent(repw, sys.trg) ){
		return CHECK_REQUEST_RETCODE_NORMAL;
	}
#endif	//PM_DEBUG

	//シェイミ変身
	{
		if ( SheimiFrmRev_CheckForm(repw) ){
			EventSet_Script(repw, SCRID_SHEIMI_FORM_REV, NULL);
			return CHECK_REQUEST_RETCODE_NORMAL;
		}
	}
	//※どんなイベントよりもダウジングマシンイベントは優先順位を低くするので、イベント追加はこれより上にしてください

	// ダウジングマシン終了
	if( req->DowsingEnd ){
		FieldSubLcdControler_ChangeApp( repw, SUBLCD_MODE_FIELD_MENU, NULL );
		return CHECK_REQUEST_RETCODE_TEL;
	}

	//電話　着信抽選 電話はダウジングよりもさらに下位
	if( req->TelCheck ){
		if(FldPMTel_CheckCallup(FldPMTel_PointerGet(repw))){
			return CHECK_REQUEST_RETCODE_TEL;
		}
	}

	return CHECK_REQUEST_RETCODE_NULL;
}

//--------------------------------------------------------------------------------------------
/**
 * 看板のイベント起動チェック
 * @param	reqw	フィールドデータ
 * @retval	"TRUE = イベント発動"
 * @retval	"FALSE = イベント発動なし"
 */
//--------------------------------------------------------------------------------------------
static BOOL CheckBoardStart( FIELDSYS_WORK * repw )
{
	FIELD_OBJ_PTR obj;
	int	id;
#if 0	//金銀で削除
	// OBJ看板チェック
	if( TalkAutoObjBoardEventCheck( repw, &obj ) == TRUE ){
		EventSet_Script( repw, FieldOBJ_EventIDGet(obj), obj );
		return TRUE;
	}
#endif
	// BG看板チェック
	id = TalkAutoBgBoardEventCheck(
			repw,(void *)EventData_GetNowBgTalkData(repw),EventData_GetNowBgTalkDataSize(repw));
	if( id != EVENT_ID_NONE ){
		EventSet_Script( repw, id, NULL );
		return TRUE;
	}

	return FALSE;
}


//============================================================================================
//============================================================================================
//--------------------------------------------------------------------------------------------
/**
 * 対戦部屋時のイベント起動チェック  by k.ohno
 * @param	req		イベントチェックリクエスト
 * @retval	"TRUE = イベント発動"
 * @retval	"FALSE = イベント発動なし"
 */
//--------------------------------------------------------------------------------------------

BOOL CheckRequestVSRoom( EV_REQUEST * req, FIELDSYS_WORK * repw )
{
	if (req->PushCheck) {  // 出口
		if (req->PushSite == DIR_DOWN && MATR_IsDownMat(GetNowAttr(repw))) {
            EventSet_Script( repw, SCRID_BATTLE_ROOM_EXIT, NULL );
			return TRUE;
		}
	}
    if(CommSysIsMoveKey() || (0 != CommPlayerGetWalkCount(CommGetCurrentID())) ||
       !CommDirectIsMoveState()){
        return FALSE;
    }

	// 会話  会話に関してはクライアントだけで処理が可能なので上と同じになる
    // ただしCommPlayerは除く
	if( req->TalkCheck ){
		{	// OBJとの会話チェック
			FIELD_OBJ_PTR obj;
			if( TalkObjEventCheck( repw, &obj ) == TRUE ){
                if(MV_PLAYER != FieldOBJ_MoveCodeGet(obj)){ // 他のプレーヤーの場合
                    if( Player_MoveForceStopCheck( repw->player ) == TRUE ){
                        Player_MoveForceStop( repw->player, Player_DirGet(repw->player) );
                    }
                    EventSet_Script( repw, FieldOBJ_EventIDGet(obj), obj );
                    return TRUE;
                }
			}
		}
	}
    if( req->TalkCheck ){    // 会話-->
        EventCmd_VSRoomTrainer(repw);
        return TRUE;
    }
	// 便利ボタンチェック
/*	if( CheckCnvButton( repw, req->CnvButton ) ){
		return TRUE;
	} */
	if( req->MenuOpen ){
		Snd_SePlay( SE_WIN_OPEN );
	    FieldMenuInitVS( repw );
		return TRUE;
	}
#ifdef	PM_DEBUG
	if( req->DebugMenu ){
		Snd_SePlay( SE_WIN_OPEN );
		FieldDebugListSet( repw );
		return FALSE;
	}
#endif	PM_DEBUG
	return FALSE;
}


static int MyStatusCheck( void );

static int MyStatusCheck( void )
{
	int i,result;
	MYSTATUS *status;

	result = 0;
	for(i=1;i<5;i++){
		status = CommInfoGetMyStatus(i);
		if(status!=NULL){
			result++;
		}
	}

	return (result>=1);
}

//============================================================================================
//============================================================================================
//--------------------------------------------------------------------------------------------
/**
 * @brief	ユニオンルーム専用イベント起動チェック
 * @param	req		イベントチェックリクエスト
 * @param	repw	ゲーム制御ワークへのポインタ
 * @retval	"TRUE = イベント発動"
 * @retval	"FALSE = イベント発動なし"
 */
//--------------------------------------------------------------------------------------------
BOOL CheckRequestUnion(const EV_REQUEST * req, FIELDSYS_WORK * repw)
{
	//話しかけられ
	//（追加予定）

	// 通信接続があった場合は絶対にイベントを開始させない
//	if(CommStateIsUnionParentConnectSuccess()){
	if(WH_GetBitmap()&0xfe){
		OS_Printf("接続中なので、イベントは発生させない bitmap=%02x status=%d connectnum=%d\n", WH_GetBitmap(), MyStatusCheck(), CommGetConnectNum());
		if(MyStatusCheck() && CommGetConnectNum()>1){

			// ●●に話しかけられました
			EventSet_Script( repw, SCRID_CONNECT_UNION_RECEIVE_OBJ, NULL );
			return TRUE;
		}
		return FALSE;
	}

	//ユニオンルームイベントチェック：会話（NPCへ）
	if( req->TalkCheck ){
		// OBJとの会話チェック
		FIELD_OBJ_PTR obj;
		if( TalkObjEventCheck( repw, &obj ) == TRUE ){
			if( Player_MoveForceStopCheck( repw->player ) == TRUE ){
				Player_MoveForceStop( repw->player, Player_DirGet(repw->player) );
			}
            CommStateChildReserve(); // 子機としてつながるので親機にはならない
			EventSet_Script( repw, FieldOBJ_EventIDGet(obj), obj );
			return TRUE;
		}
	}

	//ユニオンルームイベントチェック：出入口
	if (req->MoveCheck && MATR_IsWarpPoint(GetNowAttr(repw))) {
		EventSet_UnionRoomMapChangeOut(repw);
		return TRUE;
	}

	//ユニオンルームイベントチェック：メニュー（デバッグ含む）
	//	便利ボタンがあるならばチェックはこのあたり
	if( req->MenuOpen ){
		if(CommGetConnectNum()>1){  //つながっていたら開かない
        }
		else{
			if(SubLcdFieldMenuCheck( repw )){
				Snd_SePlay( SE_WIN_OPEN );
		    	FieldMenuInitUnion( repw );

				// 今忙しいにビーコン書き換え
				Union_BeaconChange( UNION_PARENT_MODE_BUSY );
				CommStateUnionPause();

				OS_TPrintf("MENU OPEN\n");
				return TRUE;
			}
		}
	}
#ifdef	PM_DEBUG
	if( req->DebugMenu ){
		Snd_SePlay( SE_WIN_OPEN );
		FieldDebugListSet( repw );
		return TRUE;
	}
#endif	PM_DEBUG

	return FALSE;
}

//--------------------------------------------------------------------------------------------
/**
 * バトルタワー専用イベント起動チェック
 *
 * @param	req		イベントチェックリクエスト
 *
 * @retval	"TRUE = イベント発動"
 * @retval	"FALSE = イベント発動なし"
 *
 *	リクエストを元にチェックプログラムを呼び出し、イベントを起動する
 */
//--------------------------------------------------------------------------------------------
int CheckRequestBTower(const EV_REQUEST * req, FIELDSYS_WORK * repw)
{

	//特殊スクリプト（シーン起動スクリプト）チェック
	if (req->DebugKeyPush == FALSE && SpScriptSearch(repw, SP_SCRID_SCENE_CHANGE) == TRUE) {
		return TRUE;
	}

	// 会話
	if( req->TalkCheck ){

		{	// OBJとの会話チェック
			FIELD_OBJ_PTR obj;
			if( TalkObjEventCheck( repw, &obj ) == TRUE ){

				if( Player_MoveForceStopCheck( repw->player ) == TRUE ){
					Player_MoveForceStop( repw->player, Player_DirGet(repw->player) );
				}
				if (FieldOBJ_EventTypeGet(obj) != EV_TYPE_MSG) {
					EventSet_Script( repw, FieldOBJ_EventIDGet(obj), obj );
				} else {
					EventSet_Script( repw, SCRID_COMMON_MSG, obj );
				}
				return TRUE;
			}
		}

		{	// BGの話しかけチェック
			int	id;

			id = TalkBgEventCheck(
					repw,
					(void *)EventData_GetNowBgTalkData( repw ),
					EventData_GetNowBgTalkDataSize( repw ) );

			if( id != EVENT_ID_NONE ){
				EventSet_Script( repw, id, NULL );
				return TRUE;
			}
		}
		{
			int id;
			id = EvCheck_TalkMapAttr(repw, GetFrontAttr(repw));
			if (id != EVENT_ID_NONE) {
				EventSet_Script(repw, id, NULL);
				return TRUE;
			}

		}
	}

	if (req->PushCheck) {
		if (EvCheck_ExitByPush(repw, req) == TRUE) {
			return TRUE;
		}
	}

	// 以下は、主人公の位置が無関係なイベント
	//

	// 便利ボタンチェック
	if( req->CnvButton ) {
		int ret = FieldConvButtonEventInit( repw, req->CnvButton );
		if( ret != CHECK_REQUEST_RETCODE_NULL ) {
			Request_CnvButton( repw, req->CnvButton );
			return ret;
		}
	}

	// メニューチェック
	if( req->MenuOpen ){
		Snd_SePlay( SE_WIN_OPEN );
        FieldMenuInit( repw );
		return TRUE;
	}
#ifdef	PM_DEBUG
	if( req->DebugMenu ){
		Snd_SePlay( SE_WIN_OPEN );
		FieldDebugListSet( repw );
		return TRUE;
	}
#endif	PM_DEBUG

	return FALSE;
}


//============================================================================================
//
//
//				イベント起動チェック：個別チェックルーチン
//
//
//============================================================================================

//------------------------------------------------------------------
//------------------------------------------------------------------
static BOOL CheckEncountEvent(FIELDSYS_WORK * fsys)
{
	int x, z;

	//エンカウント歩数カウントアップ
	if (fsys->encount.WalkCount < ENC_WALK_CNT_MAX){
		fsys->encount.WalkCount++;
	}

	GetNowPos(fsys, &x, &z);
	if (SysFlag_PokeParkCheck(SaveData_GetEventWork(fsys->savedata)) == TRUE) {
		if (PokeParkSys_CheckEncount(fsys, x, z) == TRUE) {
			EventSet_PokeParkBattle(fsys, PokeParkSys_SetBattleParam(fsys));
			return TRUE;
		} else {
			return FALSE;
		}
	}
#ifdef	PM_DEBUG
	if( DebugFlagData.encount_flag == 0 &&
		ZoneData_GetEncountFlag(fsys->location->zone_id) &&
		FieldEncount_Check( fsys ) == TRUE) {
		return TRUE;
	}
#else
	// エンカウント
	if( ZoneData_GetEncountFlag(fsys->location->zone_id) &&
		FieldEncount_Check( fsys ) == TRUE) {
		return TRUE;
	}
#endif	PM_DEBUG
	return FALSE;
}

//------------------------------------------------------------------
/**
 * @brief	イベント起動チェック：出入口（押し込み）
 * @param	fsys	ゲーム制御ワークへのポインタ
 * @param	req		リクエスト構造体へのポインタ
 * @retval	TRUE	イベント起動あり
 * @retval	FALSE	イベント起動なし
 */
//------------------------------------------------------------------
static BOOL EvCheck_ExitByPush(FIELDSYS_WORK * fsys, const EV_REQUEST * req)
{
	int door_id;
	int x;
	int z;
	int dir;
	u8	attr;
	LOCATION_WORK cnct;

	//押し込み操作をしていない場合、チェックしない
	if (req->PushSite == DIR_NOT) {
		return FALSE;
	}

	//梯子
	{
		//現在座標取得
		GetNowPos(fsys, &x, &z);
		//アトリビュート取得
		attr = GetAttributeLSB( fsys, x, z );
		//上り梯子表
		if ( MATR_IsUpLadderFront(attr) ){
			if( req->PushSite == DIR_UP ){
#if GS_AFTERMASTER_GF1045_20090929_FIX
        {
          BOOL rc;
          //コネクトデータを取得
          rc = GetConnectData(fsys, x, z, &cnct);
          if (rc){
            MJUMP_ChangeMap(fsys, cnct.zone_id, cnct.door_id,
                0, 0, req->PushSite, M_JUMP_LADDER_UP);
            return TRUE;
          }
        }
#else
        //コネクトデータを取得
				GetConnectData(fsys, x, z, &cnct);
				MJUMP_ChangeMap(fsys, cnct.zone_id, cnct.door_id,
							0, 0, req->PushSite, M_JUMP_LADDER_UP);
				return TRUE;
#endif
			}
			return FALSE;
		}
		//上り梯子裏
		if ( MATR_IsUpLadderBack(attr) ){
			if( req->PushSite == DIR_DOWN ){
#if GS_AFTERMASTER_GF1045_20090929_FIX
        {
          BOOL rc;
          //コネクトデータを取得
          rc = GetConnectData(fsys, x, z, &cnct);
          if (rc){
            MJUMP_ChangeMap(fsys, cnct.zone_id, cnct.door_id,
                0, 0, req->PushSite, M_JUMP_LADDER_UP);
            return TRUE;
          }
        }
#else
				//コネクトデータを取得
				GetConnectData(fsys, x, z, &cnct);
				MJUMP_ChangeMap(fsys, cnct.zone_id, cnct.door_id,
							0, 0, req->PushSite, M_JUMP_LADDER_UP);
				return TRUE;
#endif
			}
			return FALSE;
		}
	}

	//進行方向一歩前が進行不能でない場合、チェックはしない
	GetFrontPos(fsys, &x, &z);
	if (GetHitAttr(fsys, x, z) == 0) {
		return FALSE;
	}

	//進行方向一歩前の出入口チェック
	if (GetConnectData(fsys, x, z, &cnct) && req->PushSite != DIR_NOT) {
		attr = GetAttributeLSB(fsys, x, z);
		if (MATR_IsDoor(attr)) {
			MJUMP_ChangeMap(fsys, cnct.zone_id, cnct.door_id,
							0, 0, req->PushSite, M_JUMP_DOOR);
			return TRUE;
		}
#ifdef	DEBUG_ALL_EXIT_CONNECT
		//2006.03.04
		//現状は、ドア以外でも接続が存在する場合はとりあえずつないでしまう。
		//そのうちちゃんとアトリビュートが入るので廃止する予定
		EventSet_EasyMapChange(fsys, cnct.zone_id, cnct.door_id,
				0,0, Player_DirGet(fsys->player));
		return TRUE;
#endif
	}

	//現在の足元位置の出入口チェック
	GetNowPos(fsys, &x, &z);

	// マットチェック
	attr = GetAttributeLSB( fsys, x, z );
	if( MATR_IsRightMat(attr)||MATR_IsRightNoArrowMat(attr) ){
		if( req->PushSite != DIR_RIGHT ){
			return FALSE;
		}
	}else if( MATR_IsLeftMat(attr)||MATR_IsLeftNoArrowMat(attr) ){
		if( req->PushSite != DIR_LEFT ){
			return FALSE;
		}
	}else if( MATR_IsDownMat(attr)||MATR_IsDownNoArrowMat(attr) ){
		if( req->PushSite != DIR_DOWN ){
			return FALSE;
		}
	}else if( MATR_IsRightStairs(attr) ){	//右階段
		if( req->PushSite != DIR_RIGHT ){
			return FALSE;
		}
	}else if( MATR_IsLeftStairs(attr) ){	//左階段
		if( req->PushSite != DIR_LEFT ){
			return FALSE;
		}
	}

	if (GetConnectData(fsys, x, z, &cnct) == FALSE) {
		return FALSE;
	}


	{
		int type;
		if (MATR_IsDoor(attr)){					//ドア
			type = M_JUMP_DOOR;
		}else if(MATR_IsRightStairs(attr)){		//階段
			type = M_JUMP_STAIRS;
		}else if(MATR_IsLeftStairs(attr)){		//階段
			type = M_JUMP_STAIRS;
		}else if (MATR_IsRightMat(attr) || MATR_IsRightNoArrowMat(attr)
				|| MATR_IsLeftMat(attr) || MATR_IsLeftNoArrowMat(attr)
				|| MATR_IsDownMat(attr) || MATR_IsDownNoArrowMat(attr)){
			MJUMP_ChangeMapByLocation(	fsys, cnct.zone_id, cnct.door_id,
										0, 0, req->PushSite);
			return TRUE;
		}else{
			return FALSE;
		}

		MJUMP_ChangeMap(fsys, cnct.zone_id, cnct.door_id,
						0, 0, req->PushSite, type);
	}

	return TRUE;
}



//--------------------------------------------------------------------------------------------
/**
 * @brief	マップアトリビュート話しかけイベントチェック
 * @param	repw	ゲーム制御ワークへのポインタ
 * @param	matr	マップアトリビュートの値
 * @retval	EVENT_ID_NONE
 * @retval	それ以外		スクリプトのID指定
 */
//--------------------------------------------------------------------------------------------
u16 EvCheck_TalkMapAttr(FIELDSYS_WORK * repw, MATR matr)
{
	int dir = Player_DirGet(repw->player);
	int natr;

	{
		//渡されたアトリビュートに関わらず、現在地のアトリビュートも強制取得
		int	gx = Player_NowGPosXGet(repw->player);
		int	gz = Player_NowGPosZGet(repw->player);
		natr = GetAttributeLSB(repw, gx, gz);
	}

	//現在地が滝の裏特殊地形アトリビュートの場合、全チェックをスルー
	if( MATR_IsWaterfallBack(natr)){
		return EVENT_ID_NONE;
	}

	if (MATR_IsPC(matr) && dir == DIR_UP) {
		return SCRID_PC_ON;
	}else if (MATR_IsLittleBookRack01(matr)) {
		return SCRID_LITTLE_RACK1;
	}else if (MATR_IsLittleBookRack02(matr)) {
		return SCRID_LITTLE_RACK2;
	}else if (MATR_IsBookRack01(matr)) {
		return SCRID_RACK1;
	}else if (MATR_IsBookRack02(matr)) {
		return SCRID_RACK2;
	}else if (MATR_IsTrashBox(matr)) {
		return SCRID_TRASH_BOX;
	}else if (MATR_IsShopBookRack01(matr)) {
		return SCRID_SHOP_RACK1;
	}else if (MATR_IsShopBookRack02(matr)) {
		return SCRID_SHOP_RACK2;
	}else if (MATR_IsShopBookRack03(matr)) {
		return SCRID_SHOP_RACK3;
	}else if (MATR_IsMap(matr)) {
		return SCRID_TMAP_BG;
	}else if (MATR_IsTV(matr) && dir == DIR_UP) {
		return SCRID_TV;
	}else if (MATR_IsWood(matr)){
		return SCRID_FIELD_ZUTUKI;
	}

	if( Player_EventAttrCheck_KabeNobori(matr,dir) ){
		return SCRID_HIDEN_KABENOBORI;
	}

	if( Player_FormGet(repw->player) != HERO_FORM_SWIM ){
		//なみのり中でないときだけチェック
		MYSTATUS * my = SaveData_GetMyStatus(repw->savedata);
		if( Player_EventAttrCheck_Naminori(repw->player,natr,matr)
				&& MyStatus_GetBadgeFlag(my, BADGE_ID_T27)){
			if( EvPoke_CheckWaza(SaveData_GetTemotiPokemon(repw->savedata),
						WAZANO_NAMINORI) != 0xff) {
				return SCRID_HIDEN_NAMINORI;
			}
		}
		if( SafariAttr_IsEnable(repw) ){	//サファリアトリビュートが有効の時だけチェック
			if(SafariAttr_IsGroundObjPlace(matr,GetFrontHitAttr(repw))){
				return SCRID_SAFARI_OBJ_PLACE_START;
			}
		}
	}else{
		//なみのり中だけチェック
		if (MATR_IsWaterFall(matr)) {
			return SCRID_HIDEN_TAKINOBORI;
		}else if (MATR_IsUzusio(matr)){
			return SCRID_HIDEN_UZUSIO;
		}
		if( SafariAttr_IsEnable(repw) ){	//サファリアトリビュートが有効の時だけチェック
			if(SafariAttr_IsWaterObjPlace(matr,GetFrontHitAttr(repw))){
				return SCRID_SAFARI_OBJ_PLACE_START;
			}
		}
	}

	//サファリOBJ話しかけチェック
	if(	SysFlag_SafariCheck(SaveData_GetEventWork(repw->savedata)) &&
		(SafariSv_GetGameLayoutID(SaveData_GetSafariSave(repw->savedata)) == SAFARI_LAYOUT_MINE)){
		if( MATR_IsSafariObjExist(matr)){
			return SCRID_SAFARI_OBJ_TALK_START;
		}
	}
	return EVENT_ID_NONE;
}

//-------------------------------------------------------------
/**
 * @brief	一歩ごとのイベント起動チェック
 * @param	fsys	ゲーム制御ワークへのポインタ
 * @param
 *
 * @retval	BOOL		TRUE:発見	FALSE:ない
 */
//-------------------------------------------------------------
static BOOL CheckMoveEvent(FIELDSYS_WORK * fsys)
{
	u8	attr,seattr;
	int x,z;
	int dir;

	//ドラゴンジムチェック
	if (GYM_GimmickCodeCheck(fsys, FLD_GIMMICK_DRAGON_GYM)){
		if ( GYM_CheckDragonGymEvt(fsys) ){
			return TRUE;
		}
	}

	//強制移動床チェック
	dir = Player_DirGet( fsys->player );
	if( JikiEventCheck_ArrowMat(fsys,fsys->player,dir) == TRUE ){
		GYM_SetAlmGymEff(fsys, FieldOBJ_NowMapAttrGet(  Player_FieldOBJGet(fsys->player) ));
		return( TRUE );
	}

	x = Player_NowGPosXGet(fsys->player);
	z = Player_NowGPosZGet(fsys->player);

	// フィールド効果音
	FieldSeFunc(fsys, x, z );

	attr = GetAttributeLSB( fsys, x, z );


	if ( CheckPosEvent(fsys) == TRUE ) return TRUE;		// 座標発動イベントチェック
	if ( CheckExit( fsys, x, z, attr) == TRUE ){
		SetEscapeData(fsys);
		return TRUE;	// 出入り口チェック
	}
///	if ( PosAttrCheck(attr) == TRUE ) return TRUE;		// アトリビュート発動チェック
	if ( Player_MoveBitCheck_Force(fsys->player) ) {
		//自機が強制移動中は歩数がかかわる処理はフックされる
		return FALSE;
	}

	Field_SendPoketchInfo( fsys, POKETCH_SEND_PEDOMATER, 1 );

	//ボンジュースの状態アップデート
	CheckBongJuiceStep(fsys);

	if ( CheckPoison( fsys ) == TRUE ) return TRUE;		// 毒ダメージ処理
	if ( CheckSafariStep(fsys) == TRUE ) return TRUE;	// サファリ歩数チェック
	if ( CheckSodateya( fsys )==TRUE ) return TRUE;		// 育て屋処理
	if ( CheckSpray( fsys ) == TRUE )	return	TRUE;	// スプレー処理チェック
	if ( CheckTelEvent(fsys) == TRUE) return TRUE;	//電話イベントチェック

	// 128歩歩くごとに1回なつきど計算
	if( CheckFriendCalcStepCount( fsys ) ){
		DoFriendCalcStepCount( fsys );
	}

	//連れ歩きポケモン機嫌値増減
	if ( PairPoke_IsVisible(fsys) ){
		PAIR_POKE_HUMOR_ChangeVal(fsys->PairPokeHumor);
	}

	return FALSE;
}

//-------------------------------------------------------------
/**
 * @brief	POSイベントチェック
 * @param	fsys	ゲーム制御ワークへのポインタ
 *
 * @retval	BOOL		TRUE:発見	FALSE:ない
 */
//-------------------------------------------------------------
static BOOL CheckPosEvent(FIELDSYS_WORK * fsys)
{
	u16	id;
	id = PosEventCheck(
			fsys,
			(void *)EventData_GetNowPosEventData( fsys ),
			EventData_GetNowPosEventDataSize( fsys ) );
	if( id != EVENT_ID_NONE ){
		EventSet_Script( fsys, id, NULL );
		return TRUE;
	}
	return FALSE;
}

//-------------------------------------------------------------
//	 出入り口のチェック＆データセット
//-------------------------------------------------------------
static BOOL CheckExit(FIELDSYS_WORK * fsys, const int x, const int z, const u8 inAttr)
{
	LOCATION_WORK cnct;

	if (GetConnectData(fsys, x, z, &cnct) == FALSE) {
		return FALSE;
	}

	//エスカレーター
	if( MATR_IsEscalator(inAttr) == TRUE ){
		int dir = Player_DirGet( fsys->player );
		if (dir == DIR_LEFT){	//左向き
			dir = DIR_RIGHT;	//フェードイン時は右向き
		}else if (dir == DIR_RIGHT){	//右向き
			dir = DIR_LEFT;	//フェードイン時は左向き
		}else{
			GF_ASSERT(0&&"自機の向きが不正");
			return FALSE;
		}
		MJUMP_ChangeMap(fsys, cnct.zone_id, cnct.door_id,
						0, 0, dir, M_JUMP_ESCA);
		return TRUE;
	}else if ( MATR_IsEscalatorNonRet(inAttr) == TRUE ){
		int dir = Player_DirGet( fsys->player );
		if ( (dir!=DIR_LEFT)&&(dir!=DIR_RIGHT) ){
			GF_ASSERT( 0&&"自機の向きが不正" );
			return FALSE;
		}
		MJUMP_ChangeMap(fsys, cnct.zone_id, cnct.door_id,
						0, 0, dir, M_JUMP_ESCA);
		return TRUE;
	}
	//上向き踏み込みマット
	if (MATR_IsUpMat(inAttr)||MATR_IsUpNoArrowMat(inAttr)){
		MJUMP_ChangeMapByLocation(	fsys, cnct.zone_id, cnct.door_id,
										0, 0, DIR_UP);
		return TRUE;
	}
    // ワープポイント
    if(MATR_IsWarpPoint(inAttr)){
        EventCmd_WarpPoint(fsys, cnct.zone_id, cnct.door_id);
		return TRUE;
    }

	//下り梯子
	if (MATR_IsDownLadder(inAttr)){
		MJUMP_ChangeMap(fsys, cnct.zone_id, cnct.door_id,
						0, 0, DIR_UP, M_JUMP_LADDER_DOWN);
		return TRUE;
	}

#ifdef	DEBUG_ALL_EXIT_CONNECT
	//2006.03.04
	//アトリビュートがないが出入口がある場合、とりあえずつなぐ
	//最終的にはこの処理は全てのアトリビュートがそろえば不要となる
	if (
			MATR_IsLeftStairs(inAttr) ||
			MATR_IsRightStairs(inAttr) ||
			MATR_IsDownMat(inAttr) ||
//			MATR_IsUpMat(inAttr) ||
			MATR_IsLeftMat(inAttr) ||
			MATR_IsRightMat(inAttr) ||
			MATR_IsDownNoArrowMat(inAttr) ||
//			MATR_IsUpNoArrowMat(inAttr) ||
			MATR_IsLeftNoArrowMat(inAttr) ||
			MATR_IsRightNoArrowMat(inAttr)) {
		//上にのって押し込むタイプのアトリビュートの場合は無視する
		return FALSE;
	}
	EventSet_EasyMapChange(fsys, cnct.zone_id, cnct.door_id,
			0,0, Player_DirGet(fsys->player));

	return TRUE;
#endif

/**
			//温泉
			//隠し落とし穴
			//ワープポイント
			//落とし穴
			//OBJ位置保持ワープポイント
*/

	return FALSE;
}

//==============================================================================
/**
 * @brief   育て屋チェック呼び出し
 *
 * @param   fsys
 *
 * @retval  BOOL
 */
//==============================================================================
static BOOL CheckSodateya( FIELDSYS_WORK *fsys )
{
	POKEPARTY     *myparty  = SaveData_GetTemotiPokemon(fsys->savedata);
	SODATEYA_WORK *sodateya = SaveData_GetSodateyaWork(fsys->savedata);

	// 育て屋１歩歩き処理
	if (PokeSodateya( sodateya, myparty, fsys ) == TRUE) {
		RECORD *record = SaveData_GetRecord(fsys->savedata);

		// タマゴが生まれた回数を＋１
		RECORD_Inc( record, RECID_TAMAGO_HATCHING );
		// スコア加算
		RECORD_Score_Add( record, SCORE_ID_EGG_HATCHING );

		// タマゴが孵化したイベント発動
		EventSet_Script(fsys, SCRID_EGG_HATCHING, NULL);


		return TRUE;
	} else {
		return FALSE;
	}
}

//==============================================================================
/**
 * @brief   スプレー処理
 *
 * @param   fsys
 *
 * @retval  BOOL		TRUEだったら、スプレー効果切れたメッセージ表示
 */
//==============================================================================
static BOOL CheckSpray( FIELDSYS_WORK *fsys )
{
	return Spray_DecSpray(fsys->savedata, fsys);
}

//----------------------------------------------------------------------------
/**
 *	@brief	連れ歩き　なつき度検査
 *
 *	@param	fsys	フィールドシステム
 *
 *	@retval	TRUE	なつき度計算する
 *	@retval	FALSE	なつき度計算しない
 */
//-----------------------------------------------------------------------------
static BOOL CheckFriendCalcStepCount( FIELDSYS_WORK *fsys )
{
	u16 step;
	EVENTWORK* ev;
	BOOL ret = FALSE;

	ev = SaveData_GetEventWork( fsys->savedata );
	step = SysWork_FriendlyStepCountGet( ev );
	step ++;
	if( step >= FRIENDCALC_STEP_MAX ){
		step = 0;
		ret = TRUE;
	}
	SysWork_FriendlyStepCountSet( ev, step );

	return ret;
}

//----------------------------------------------------------------------------
/**
 *	@brief	なつき度計算を行う
 *
 *	@param	fsys	フィールドシステム
 */
//-----------------------------------------------------------------------------
static void DoFriendCalcStepCount( FIELDSYS_WORK *fsys )
{
	int i, max;
	POKEMON_PARAM * pp;
	POKEPARTY *party  = SaveData_GetTemotiPokemon(fsys->savedata);
	u16 placeID = ZoneData_GetPlaceNameID(fsys->location->zone_id);

	max = PokeParty_GetPokeCount(party);

	for( i=0; i<max; i++ ){
		pp = PokeParty_GetMemberPointer(party, i);
		FriendCalc( pp, FRIEND_TSUREARUKI, placeID );
	}
}



//==============================================================================
//==============================================================================
//-------------------------------------------------------------
/**
 * @brief	毒ダメージチェック
 * @param	fsys		フィールド制御データへのポインタ
 * @return	BOOL	TRUEのとき毒による死亡ダメージ発動
 *
 * 内部で毒エフェクトの呼び出しを行っている
 */
//-------------------------------------------------------------
static BOOL CheckPoison(FIELDSYS_WORK * fsys)
{
	POKEPARTY     *myparty  = SaveData_GetTemotiPokemon(fsys->savedata);
	u16 *poison_step = Situation_GetPoisonStepCount(SaveData_GetSituation(fsys->savedata));
	(*poison_step) ++;
	(*poison_step) %= POISON_STEP_MAX;
	if (*poison_step != 0) {
		return FALSE;
	}

	switch (EvPoke_PoisonDamage(myparty, ZoneData_GetPlaceNameID(fsys->location->zone_id))){
	case FLD_POISON_NODAMAGE:
		return FALSE;
	case FLD_POISON_DAMAGE:
		POISON_EFFE_Start(fsys->fldmap->poisoneffect);
		return FALSE;
	case FLD_POISON_DEAD:
		POISON_EFFE_Start(fsys->fldmap->poisoneffect);
		EventSet_Script(fsys, SCRID_POISON_DEAD, NULL);
		return TRUE;
	}
	return FALSE;
}
//==============================================================================
//==============================================================================
//-------------------------------------------------------------
/**
 * @brief	サファリ歩数チェック
 * @param	fsys		フィールド制御データへのポインタ
 * @return	BOOL	TRUEのとき歩数終了イベント発動
 *
 */
//-------------------------------------------------------------
static BOOL CheckSafariStep(FIELDSYS_WORK * fsys)
{
	u16 * safari_ball;
	//サファリモードでなければチェックしない
	if (SysFlag_SafariCheck(SaveData_GetEventWork(fsys->savedata)) == FALSE) {
		return FALSE;
	}

	safari_ball = Situation_GetSafariBallCount(SaveData_GetSituation(fsys->savedata));
	if (*safari_ball == 0) {
		EventSet_Script(fsys, SCRID_SAFARI_ANNOUNCE_BALL, NULL);
		return TRUE;
	}
	return FALSE;
}

//-------------------------------------------------------------
/**
 * @brief	歩数関連電話イベント発動チェック
 * @param	fsys		フィールド制御データへのポインタ
 *
 * 内部で条件をチェックし、電話イベントの予約をします
 */
//-------------------------------------------------------------
static BOOL CheckTelEvent(FIELDSYS_WORK * fsys)
{
	PMTEL_SAVE* tel_save = SaveData_GetPMTelSave(fsys->savedata);
	EVENTWORK* ev_save = SaveData_GetEventWork(fsys->savedata);

	 //自転車譲渡イベントチェック
	 if(!EventWork_CheckEventFlag(ev_save,SYS_FLAG_TRANSFER_BYCYCLE)){
		//既に予約中か？
		if( !PMTelSv_CallReserveCheck(tel_save,PMTEL_RESERVE_CYCLE)){
			//自転車移動の歩数チェック
			if(RECORD_Get(SaveData_GetRecord(fsys->savedata), RECID_WALK_COUNT_CYCLE) >= 1024){
				//予約
				FldPMTel_IncomingReservation(FldPMTel_PointerGet(fsys),PMTEL_RESERVE_CYCLE,TRUE);
#if 0
				FldPMTel_CallParamSet(FldPMTel_PointerGet(fsys),
					PMTEL_NUMBER_CYCLE,TEL_RECEIVE_EVENT,TEL_TK_CYCLE_TRANSFER);
				// タマゴが孵化したイベント発動
				EventSet_Script(fsys, SCRID_CALL_PGEAR_TEL_EV_CHECK, NULL);
#endif
				return FALSE;
			}
		}
	}
	return FALSE;
}
//-------------------------------------------------------------
/**
 * @brief	虫取り時間経過チェック
 * @param	fsys		フィールド制御データへのポインタ
 * @return	BOOL	TRUEのとき時間終了イベント発動
 *
 */
//-------------------------------------------------------------
static BOOL CheckMushitoriTime(FIELDSYS_WORK * fsys)
{
	FLD_MUSHITORI_WORK* wk = MushitoriSysSt_GetWorkPointer(fsys);

	//虫取り大会モードでなければチェックしない
	if (SysFlag_MushitoriCheck(SaveData_GetEventWork(fsys->savedata)) == FALSE) {
		return FALSE;
	}
	if (wk->time >= MUSHITORI_TIME_MAX) {
		EventSet_Script(fsys, SCRID_MUSHI_ANNOUNCE_TIME, NULL);
		return TRUE;
	}
	return FALSE;
}

//-------------------------------------------------------------
/**
 * @brief	ボンジュース歩数チェック
 * @param	fsys		フィールド制御データへのポインタ
 * @return	BOOL	TRUEのとき歩数終了イベント発動
 *
 */
//-------------------------------------------------------------
static void CheckBongJuiceStep(FIELDSYS_WORK * fsys)
{
	u32 walk_ct;

	walk_ct	= RECORD_Get(SaveData_GetRecord(fsys->savedata),RECID_WALK_COUNT);

	BonguriSave_JuiceStateUpdate(SaveData_GetBonguriSave(fsys->savedata),walk_ct);
}


//============================================================================================
//
//
//		イベント起動チェック用ツール関数
//
//
//============================================================================================
//-------------------------------------------------------------
//-------------------------------------------------------------
static void GetNowPos(const FIELDSYS_WORK * fsys, int *x, int *z)
{
	*x = Player_NowGPosXGet(fsys->player);
	*z = Player_NowGPosZGet(fsys->player);
}

//-------------------------------------------------------------
/**
 */
//-------------------------------------------------------------
static void GetFrontPos(const FIELDSYS_WORK * fsys, int * x, int * z)
{
	int dir;
	dir = Player_DirGet(fsys->player);
	GetMovePos(fsys, dir, x, z);
}

//-------------------------------------------------------------
//-------------------------------------------------------------
static void GetMovePos(const FIELDSYS_WORK * fsys, int dir, int * x, int * z)
{
	GetNowPos(fsys, x, z);
	switch (dir) {
	case DIR_UP:
		*z -= 1;
		break;
	case DIR_DOWN:
		*z += 1;
		break;
	case DIR_LEFT:
		*x -= 1;
		break;
	case DIR_RIGHT:
		*x += 1;
		break;
	default:
		GF_ASSERT_MSG("自機の方向がおかしい\n",0);
	}
}

//-------------------------------------------------------------
/**
 */
//-------------------------------------------------------------
static u8 GetNowAttr(const FIELDSYS_WORK * fsys)
{
	int x,z;
	GetNowPos(fsys, &x, &z);
	return GetAttributeLSB(fsys, x, z);
}

//-------------------------------------------------------------
/**
 */
//-------------------------------------------------------------
static u8 GetFrontAttr(const FIELDSYS_WORK * fsys)
{
	int x,z;
	GetFrontPos(fsys, &x, &z);
	return GetAttributeLSB(fsys, x, z);
}

//-------------------------------------------------------------
/**
 */
//-------------------------------------------------------------
static u8 GetFrontHitAttr(const FIELDSYS_WORK * fsys)
{
	int x,z;
	GetFrontPos(fsys, &x, &z);
	return GetHitAttr(fsys, x, z);
}


//-------------------------------------------------------------
/**
 * @brief	接続データの取得
 * @param	fsys		フィールド制御データへのポインタ
 * @param	x			接続データを探すX位置（グリッド単位）
 * @param	z			接続データを探すY位置（グリッド単位）
 * @retval	CONNECT_DATA	接続データのアドレス
 * @retval	NULL			接続データがなかった場合
 */
//-------------------------------------------------------------
static BOOL GetConnectData(const FIELDSYS_WORK * fsys, int x, int z,
		LOCATION_WORK * next)
{
	const CONNECT_DATA * connect;
	int door_id;
	door_id = EventData_SearchNowConnectIDByXZ(fsys, x, z);
	if (door_id == -1) {
		return FALSE;
	}
	connect = EventData_GetNowConnectDataByID(fsys, door_id);
	if (connect == NULL) {
		return FALSE;
	}
	if (connect->link_door_id == SPECIAL_SPEXIT01) {
		GF_ASSERT(connect->link_zone_id == ZONE_ID_SPECIAL);
		*next = *(Situation_GetSpecialLocation(SaveData_GetSituation(fsys->savedata)));
	} else {
		SetLocation(next, connect->link_zone_id, connect->link_door_id,
				connect->x, connect->z, DIR_DOWN);
	}
	{
		//今入ることになる出入口の情報を覚えておく
		LOCATION_WORK * ent = Situation_GetEntranceLocation(SaveData_GetSituation(fsys->savedata));
		SetLocation(ent, fsys->location->zone_id, door_id, x, z, Player_DirGet(fsys->player));
	}
	return TRUE;
}

//--------------------------------------------------------------------------------------------
/**
 * エスケープデータセット
 *
 * @param	fsys			フィールドシステムポインタ
 * @param	inX				復帰Ｘ座用
 * @param	inZ				復帰Ｚ座標
 * @param	inDir			入った時の向き
 *
 * @return	none
 */
//--------------------------------------------------------------------------------------------
static void SetEscapeDataCore(FIELDSYS_WORK * fsys, const int inX, const int inZ, const int inDir)
{
	SITUATION * sit = SaveData_GetSituation(fsys->savedata);
	LOCATION_WORK * escape = Situation_GetEscapeLocation(sit);
	(*escape) = *(fsys->location);
	escape->dir = inDir;
	escape->grid_x = inX;
	escape->grid_z = inZ;
	if (inDir == DIR_UP){
		(escape->grid_z)++;
	}
	escape->zone_id = fsys->location->zone_id;
	escape->door_id = DOOR_ID_JUMP_CODE;
}

//--------------------------------------------------------------------------------------------
/**
 * エスケープデータセット
 *
 * @param	fsys			フィールドシステムポインタ
 *
 * @return	none
 */
//--------------------------------------------------------------------------------------------
static void SetEscapeData(FIELDSYS_WORK * fsys)
{
	int x,z;
	LOCATION_WORK cnct;

	GetNowPos(fsys, &x, &z);
	if ( GetConnectData(fsys, x, z, &cnct) ) {
		if (ZoneData_IsSinouField(fsys->location->zone_id) == TRUE
				&& ZoneData_IsSinouField(cnct.zone_id) == FALSE) {
			SetEscapeDataCore(fsys, x, z, Player_DirGet(fsys->player));
		}
	}else{
		GetFrontPos(fsys, &x, &z);
		if ( GetConnectData(fsys, x, z, &cnct) ) {
			if (ZoneData_IsSinouField(fsys->location->zone_id) == TRUE
					&& ZoneData_IsSinouField(cnct.zone_id) == FALSE) {
				SetEscapeDataCore(fsys, x, z, Player_DirGet(fsys->player));
			}
		}
	}
}

#define FIELD_SE_DATA_1GRID_SIZE	( 8 )
//------------------------------------------------------------------
/**
 * @brief   矩形領域の連続比較の中でヒットしたSE情報を格納して返す
 *
 * @param   fst		FIELD_SE_TABLEのポインタ
 * @param   x		主人公のX座標
 * @param   y		主人公のZ座標
 *
 * @retval  int		ヒットしなかったら-1・ヒットしたら配列の番号
 */
//------------------------------------------------------------------
static int FieldSeAttrHitCheck( const FIELD_SE_TABLE *fst, const int x, const int y )
{
	int i,ret=-1;
	int lx = x % BLOCK_GRID_W;
	int ly = y % BLOCK_GRID_H;

	// 矩形領域の連続比較（シューティングの弾と自分の比較みたいなもの）
	for(i=0; i<fst->size/FIELD_SE_DATA_1GRID_SIZE; i++){
		if( fst->setable[i].x1<=lx && lx<=fst->setable[i].x2){
			if( fst->setable[i].y1<=ly && ly<=fst->setable[i].y2){
				ret = i;
			}
		}
	}
#if 0
	if(ret!=-1){
		OS_Printf("x=%d, y=%d, ret=%d, se=%d\n", lx, ly,  ret, fst->setable[ret].se);
		OS_Printf("x1=%d, y1=%d, x2=%d, y2=%d\n", fst->setable[ret].x1, fst->setable[ret].y1, fst->setable[ret].x2, fst->setable[ret].y2 );
	}
#endif
	return ret;
}

#define FIELD_SE_MAX	( 16 )
//------------------------------------------------------------------
// フィールド環境音定義テーブル
//------------------------------------------------------------------
typedef struct{
	u16 seqNo;				// シーケンスナンバー
	u16	bgm_bank_flag;		// ゾーンBGMのバンクを使用してSE再生されるかフラグ
}FIELD_SE_WORK;

#if 0
////////////////////////////////////////////////////////////////////
seqNoは、
エリアの違いは関係なく環境音ごとに登録してください
再生関数の中で、バンクを切り替えて鳴るようにしています

bgm_bank_flagは、
ゾーンBGMのバンクを使用して鳴らすSEか、
フィールドSEバンクを使用して鳴らすSEか、
を判断するためのフラグです。
08.10.15現在では、
「海辺」「風車」の音のみ、フィールドSEバンクを使用していて、
それ以外「せせらぎ」などの音はゾーンBGMのバンクを使用しています。
////////////////////////////////////////////////////////////////////
#endif

static const FIELD_SE_WORK FieldSeTable[]={
	{ SEQ_SE_GS_N_SESERAGI,		1 },	// せせらぎ
	{ SEQ_SE_GS_N_HUUSHA,		0 },	// 風車
	{ SEQ_SE_GS_N_UMIBE,		0 },	// 海辺
	{ SEQ_SE_GS_N_HASHIRA,		1 },	// 柱のきしみ
	{ SEQ_SE_GS_N_UZUSIO,		0 },	// うずしお
	{ SEQ_SE_GS_N_TAKI,			0 },	// 滝
	{ SEQ_SE_GS_N_YOUGAN,		1 },	// 溶岩
	{ SEQ_SE_GS_N_KANSEI,		0 },	// 歓声 （風を削除した（ 09.03.14 by Mori)）
	{ SEQ_SE_GS_N_KITEKI,		0 },	// 汽笛
	{ SEQ_SE_GS_KABIGON_IBIKI,	1 },	// カビゴン
	{ SEQ_SE_GS_N_MOTER,		1 },	// モーター
	{ SEQ_SE_GS_N_KANE,			1 },	// 鐘
	{ SEQ_SE_GS_KYOUHUU,		1 },	// リニア
	{ SEQ_SE_GS_N_ENGINE,		1 },	// エンジン
	{ SEQ_SE_GS_N_HUNSUI,		0 },	// 噴水
	{ SEQ_SE_GS_DENGEKIBARIA,	0 },	// 電気
};

#include "field_se.dat"

//----------------------------------------------------------------------------------
/**
 * フラグ条件によって環境音を鳴らさないチェック
 *
 * @param   fsys
 * @param   seattr		se番号
 *
 * @retval  int			1:鳴らす	0:鳴らさない
 */
//----------------------------------------------------------------------------------
static int FieldSe_CheckCancel( FIELDSYS_WORK *fsys, FIELD_SE_TABLE *fld_se_table, const int seattr )
{
	EVENTWORK *ev = SaveData_GetEventWork(fsys->savedata);
	int seNo = FieldSeTable[fld_se_table->setable[seattr].se].seqNo;
	LOCATION_WORK * now = Situation_GetNowLocation(SaveData_GetSituation(fsys->savedata));

#if 0
	//滝音オフになっていて、滝音を再生しようとしていたら何もしない
	if( (SysFlag_GymSeCheck(ev) == TRUE) &&
		(seNo==SEQ_SE_GS_N_TAKI || seNo==SEQ_SE_GS_DENGEKIBARIA)){
		return 0;
	}
#else	//BTS5086修正
	//タンバジム専用制御
	if(now->zone_id == ZONE_ID_T24GYM0101){
		if( (SysFlag_TanbaGymSeCheck(ev) && (seNo == SEQ_SE_GS_N_TAKI))){
			return 0;
		}
	}
	//クチバジム専用制御
	if(now->zone_id == ZONE_ID_T06GYM0101){
		if( (SysFlag_KutibaGymSeCheck(ev) && (seNo == SEQ_SE_GS_DENGEKIBARIA))){
			return 0;
		}
	}
#endif

	// カビゴンチェック
	if( (SysFlag_CheckR11Kabigon(ev) == TRUE) &&
		(seNo==SEQ_SE_GS_KABIGON_IBIKI)){
#ifdef PM_DEBUG
		OS_Printf("カビゴンいびきスルー\n");
#endif
		return 0;
	}

	if(SysFlag_CheckRocketAzitoEnd( ev ) && (seNo==SEQ_SE_GS_N_MOTER)){
		OS_Printf("モーター音スルー\n");
		return 0;
	}

	return 1;
}
//------------------------------------------------------------------
/**
 * @brief   フィールド効果音処理
 *
 * @param   fsys	FIELDSYS_WORK*
 * @param   x		主人公X
 * @param   z		主人公Z
 *
 * @retval  none
 */
//------------------------------------------------------------------
static void FieldSeFunc( FIELDSYS_WORK *fsys, const int x, const int z )
{
// とにかく環境音を無視
#ifdef NO_FIELD_SE
	FIELD_SE_TABLE *fld_se_table;
	int seattr,no;

	return;

 	fld_se_table =  (FIELD_SE_TABLE *)MPTL_GetEnvSoundData(fsys, x, z);

#else
	FIELD_SE_TABLE *fld_se_table =  (FIELD_SE_TABLE *)MPTL_GetEnvSoundData(fsys, x, z);
	int seattr,no;
#endif


	if(fsys->field_se_no==FIELD_SE_REPLAY_REQUEST){
		fsys->field_se_no=FIELD_SE_REPLAY_NONE;
	}else if(fsys->field_se_no==FIELD_SE_REPLAY_REQUEST_MAP_CHG){
		fsys->field_se_no=FIELD_SE_REPLAY_NONE;
	}

	// フィールド効果音矩形テーブルと自機座標を比較してフィールド効果音アトリビュートを取得
	seattr=FieldSeAttrHitCheck(fld_se_table, x, z);
	OS_Printf("seattr=%d, field_se_no=%d\n",seattr, fsys->field_se_no);
	if(seattr!=-1){

		// フラグ条件で環境音を鳴らさないチェックがある
		if( !FieldSe_CheckCancel( fsys, fld_se_table, seattr ) ){
			return;
		}

		// フィールド効果音の最大定義数を超えていないかチェック
		if(fld_se_table->setable[seattr].se < FIELD_SE_MAX){
			if(fsys->field_se_no!=FieldSeTable[fld_se_table->setable[seattr].se].seqNo){

				if( FieldSeTable[fld_se_table->setable[seattr].se].bgm_bank_flag == 1 ){
					//ゾーンBGMのバンクを使用してSEを再生
					Snd_SePlay_ZoneBgmBank( FieldSeTable[fld_se_table->setable[seattr].se].seqNo );
#ifdef PM_DEBUG
					if(FieldSeTable[fld_se_table->setable[seattr].se].seqNo==SEQ_SE_GS_KABIGON_IBIKI){
						OS_Printf("いびき　コール！\n");
					}
#endif
				}else{
					//サウンド設定ファイルのバンク指定でSE再生
					Snd_SePlay( FieldSeTable[fld_se_table->setable[seattr].se].seqNo );

				}
			}

			// 再生終了用にSE番号を保存
			fsys->field_se_no = FieldSeTable[fld_se_table->setable[seattr].se].seqNo;

			// フィールド効果音が鳴っている時のBGMの音量設定
			if(fld_se_table->setable[seattr].vol < FIELD_SE_VOLUME_MAX){
				Snd_PlayerMoveVolume(	SND_HANDLE_FIELD,
										BgmVolumeTable[fld_se_table->setable[seattr].vol],
										EV_BGM_VOL_FADE_FRAME );

				no = fld_se_table->setable[seattr].se;
				Snd_PlayerMoveVolume(	SND_HANDLE_SE_3,
										SeVolumeTable[no][fld_se_table->setable[seattr].vol],
										EV_SE_VOL_FADE_FRAME );

#if EV_BGM_SE_VOL_TEST_PRINT
				OS_Printf( "vol_lv 0small 1big 2bigbig= %d\n", fld_se_table->setable[seattr].vol );
				OS_Printf( "field se no = %d\n", no );
				OS_Printf( "bgm vol = %d\n", BgmVolumeTable[fld_se_table->setable[seattr].vol] );
				OS_Printf( "se vol = %d\n", SeVolumeTable[no][fld_se_table->setable[seattr].vol] );
#endif
			}

		}else{
			GF_ASSERT(seattr<FIELD_SE_MAX && "FIELD_SE is MAX over.");
		}

	}else{
		// 保存用のワークに再生した後がある場合は再生ストップ呼び出し
#if GS_BTS5539_20090709_FIX
		if(seattr==FIELD_SE_NONE_NO){
			Snd_SeStop(SND_HANDLE_SE_3,10);
#else
		if(fsys->field_se_no != FIELD_SE_NONE_NO){
			Snd_SeStopBySeqNo( fsys->field_se_no, 10 );
#endif
			Snd_PlayerMoveVolume(	SND_HANDLE_FIELD, 128,	EV_BGM_VOL_FADE_FRAME );
			fsys->field_se_no = FIELD_SE_NONE_NO;
		}
	}
	// 落葉を踏む音の処理はplayer_move.cに移動しました。

}


//==============================================================================
/**
 * @brief   フィールド初期化時にフィールド効果音をチェックして再生開始を行う
 *
 * @param   fsys	FIELDSYS_WORK
 * @param   flag	環境音情報を上書きするか？（TRUE=する)
 *
 * @retval  none
 */
//==============================================================================
void FieldSeSetup( FIELDSYS_WORK *fsys, BOOL flag )
{
	int x,z;

// とにかく環境音を無視
#ifdef NO_FIELD_SE
	return;
#endif
	//写真モードの場合は効果音処理を行わない
	if (fsys->picture_mode_flag){
		return;
	}
	// 主人公の位置を取得
	x = Player_NowGPosXGet(fsys->player);
	z = Player_NowGPosZGet(fsys->player);

	// それまでの環境音情報を上書きするか？（TRUE
	if(flag){
		fsys->field_se_no = FIELD_SE_NONE_NO;
	}

	// 効果音アトリビュートと比較してフィールド効果音の再生処理を呼び出し
	FieldSeFunc( fsys, x, z );
	OS_Printf("x=%d, z=%d\n", x, z);
}

//--------------------------------------------------------------------------------------------
/**
 * @brief	木範囲外話しかけチェック
 * @param	repw	ゲーム制御ワークへのポインタ
 * @retval	EVENT_ID_NONE
 * @retval	それ以外		スクリプトのID指定
 */
//--------------------------------------------------------------------------------------------
static u16 CheckTreeOutRange(FIELDSYS_WORK * repw)
{
	if ( FieldCheck_CheckTreeOutRange(repw) ){
		return SCRID_FIELD_ZUTUKI;
	}
	return EVENT_ID_NONE;
}

//------------------------------------------------------------------
/**
 * @brief   目の前で起こせるイベントチェック
 *
 * @param   wk
 *
 * @retval  int
 */
//------------------------------------------------------------------
int FieldCheck_FrontAction( FIELDSYS_WORK *fsys )
{
	FIELD_OBJ_PTR obj;
	int id;
	if(TalkObjEventCheck( fsys, &obj )==TRUE){
		switch(FieldOBJ_EventTypeGet(obj)){
		case EV_TYPE_ITEM:
			return 0;
			break;
		case EV_TYPE_NORMAL:
			return 1;
			break;
		default:
			return 1;
		}
	}

	id = TalkBgEventCheck(
			fsys,
			(void *)EventData_GetNowBgTalkData( fsys ),
			EventData_GetNowBgTalkDataSize( fsys ) );

	if( id != EVENT_ID_NONE ){
		return 2;
	}
	return 0;
}

//------------------------------------------------------------------
/**
 * @brief   目の前が範囲外の木か？
 *
 * @param   fsys		フィールドシステムポインタ
 *
 * @retval  BOOL		TRUE:範囲外木
 */
//------------------------------------------------------------------
BOOL FieldCheck_CheckTreeOutRange( FIELDSYS_WORK *fsys )
{
	int x,z;
	u16 block_idx, arc_idx;

	//主人公の目の前の座標を取得
	GetFrontPos(fsys, &x, &z);
	//取得座標のブロックインデックスを計算
	block_idx = MPTL_GetBlockIdx(fsys, x, z);
	//ブロックインデックスのアーカイブ番号を取得
	arc_idx = GetWorldMapArcIdx(block_idx, fsys->World);
	//アーカイブインデックスが木の範囲外かをチェック
	if ( MPTL_IsTreeOutRange(arc_idx) ){
		OS_Printf("範囲外の木を検出\n");
		return TRUE;
	}

	return FALSE;
}

#ifdef AFTERMASTER_BTL_REC_FORCE_SVAE

static u16 debug_seq1;
static u16 debug_seq2;
static u8 debug_count;

static void DBG_CreateBtlRecSvEvt(FIELDSYS_WORK * fsys)
{
  //イベント作成
  debug_seq1 = 0;
  debug_seq2 = 0;
  debug_count = 1;    //自分のデータはフラグを立てないので1からスタート

  FieldEvent_Set(fsys, BtlRecSvEvt, NULL);
}

static BOOL BtlRecSvEvt(GMEVENT_CONTROL * event)
{
  FIELDSYS_WORK * fsys = FieldEvent_GetFieldSysWork(event);
  int * seq = FieldEvent_GetSeqWork(event);

  switch(*seq){
  case 0:
    OS_Printf("セーブに必要なデータを収集\n");
    Field_SaveParam_BattleRecorder(fsys);
    OS_Printf("%d::レコーダーデータロード\n",debug_count);
    {
      LOAD_RESULT load_result;
      //ロード
      BattleRec_Load(fsys->savedata, HEAPID_FIELD, &load_result, NULL, debug_count);
      if (load_result == RECLOAD_RESULT_OK){
        OS_Printf("データ発見\n");
        //フラグセット
        DBG_BattleRec_SecureFlagSet(fsys->savedata);
        (*seq)++;
      }else{
        OS_Printf("データなし\n");
        (*seq) = 2;
        break;
      }
    }
    //no break;
  case 1:
    {
      SAVE_RESULT save_result;
      //セーブ
      save_result = DBG_BattleRec_Save(fsys->savedata, debug_count, &debug_seq1, &debug_seq2);
///      save_result = DBG_save(fsys->savedata, debug_count);

      if(save_result == SAVE_RESULT_OK){
        (*seq)++;
      }
    }
    break;
  case 2:
    if (brs != NULL){
      BattleRec_Exit();
    }
    //カウントアップ
    debug_count++;
    //シーケンスクリア
    debug_seq1 = 0;
    debug_seq2 = 0;
    if (debug_count>=4){
      //終了
      OS_Printf("終了\n");
      return TRUE;
    }else{
      OS_Printf("次のデータ\n");
      (*seq) = 0;
    }
  }

  return FALSE;
}

//--------------------------------------------------------------
/**
 * @brief   読み込み済みのbrsに対してsecureフラグをセットする
 *
 * @param   sv
 */
//--------------------------------------------------------------
static void DBG_BattleRec_SecureFlagSet(SAVEDATA *sv)
{
	GF_ASSERT(brs != NULL);

	brs->head.secure = TRUE;
	//secureフラグが更新されたので、再度CRCを作り直す
	brs->head.magic_key = REC_OCC_MAGIC_KEY;
	brs->head.crc.crc16ccitt_hash = SaveData_CalcCRC(sv, &brs->head,
		sizeof(BATTLE_REC_HEADER) - GDS_CRC_SIZE - DATANUMBER_SIZE);
}

#if 0
static SAVE_RESULT DBG_save(SAVEDATA *sv, int num)
{
  SAVE_RESULT result;

	GF_ASSERT(brs != NULL);

	brs->head.secure = TRUE;
	//secureフラグが更新されたので、再度CRCを作り直す
	brs->head.magic_key = REC_OCC_MAGIC_KEY;
	brs->head.crc.crc16ccitt_hash = SaveData_CalcCRC(sv, &brs->head,
		sizeof(BATTLE_REC_HEADER) - GDS_CRC_SIZE - DATANUMBER_SIZE);

	//CRCをキーにして暗号化
	BattleRec_Coded(&brs->rec, sizeof(BATTLE_REC_WORK) - GDS_CRC_SIZE,
		brs->rec.crc.crc16ccitt_hash + ((brs->rec.crc.crc16ccitt_hash ^ 0xffff) << 16));

	sys_SoftResetNG(SOFTRESET_TYPE_VIDEO);
	result = SaveData_Extra_SaveBattleRecData(sv, brs, num);
/**
  if(result == SAVE_RESULT_OK){
		result = SaveData_Save(sv);
	}
*/
	sys_SoftResetOK(SOFTRESET_TYPE_VIDEO);
	return result;

}
#endif
static SAVE_RESULT DBG_BattleRec_Save(SAVEDATA *sv, int num, u16 *work0, u16 *work1)
{
	BATTLE_REC_HEADER *head;
  BATTLE_REC_WORK *rec;
	SAVE_RESULT result;

	switch(*work0){
	case 0:
		//データがないときは、何もしない
		if(brs==NULL){
			return	SAVE_RESULT_NG;
		}

    brs->head.secure = TRUE;

    head = &brs->head;
    rec = &brs->rec;
		//CRC作成
		head->magic_key = REC_OCC_MAGIC_KEY;
		head->crc.crc16ccitt_hash = SaveData_CalcCRC(sv, head,
			sizeof(BATTLE_REC_HEADER) - GDS_CRC_SIZE - DATANUMBER_SIZE);

		//CRCをキーにして暗号化
		BattleRec_Coded(rec, sizeof(BATTLE_REC_WORK) - GDS_CRC_SIZE,
			rec->crc.crc16ccitt_hash + ((rec->crc.crc16ccitt_hash ^ 0xffff) << 16));

		*work1 = 0;
		(*work0)++;
		break;
	case 1:
		result = DBG_Local_BattleRecSave(sv, brs, num, work1);
		return result;
	}

	return SAVE_RESULT_CONTINUE;
}

//--------------------------------------------------------------
/**
 * @brief   対戦録画のセーブ処理をまとめたもの
 *
 * @param   sv		セーブデータへのポインタ
 * @param   num		LOADDATA_MYREC、LOADDATA_DOWNLOAD0、LOADDATA_DOWNLOAD1…
 * @param   seq		セーブ進行を制御するワークへのポインタ(最初は0クリアした状態で呼んで下さい)
 *
 * @retval	SAVE_RESULT_CONTINUE	セーブ継続中
 * @retval	SAVE_RESULT_LAST		セーブ継続中、最後の部分
 * @retval	SAVE_RESULT_OK			セーブ終了、成功
 * @retval	SAVE_RESULT_NG			セーブ終了、失敗
 */
//--------------------------------------------------------------
static SAVE_RESULT DBG_Local_BattleRecSave(SAVEDATA *sv, BATTLE_REC_SAVEDATA *work, int num, u16 *seq)
{
	SAVE_RESULT result;

	switch(*seq){
	case 0:
		sys_SoftResetNG(SOFTRESET_TYPE_VIDEO);
    OS_Printf("外部データセーブ中\n");
		result = SaveData_Extra_SaveBattleRecData(sv,work,num);
		if(result == SAVE_RESULT_OK){
      OS_Printf("通常セーブ開始\n");
			//result = SaveData_Save(sv);
			SaveData_DivSave_Init(sv, SVBLK_ID_MAX);
			(*seq)++;
			return SAVE_RESULT_CONTINUE;
		}

		sys_SoftResetOK(SOFTRESET_TYPE_VIDEO);
		return result;
	case 1:
		result = SaveData_DivSave_Main(sv);
		if(result == SAVE_RESULT_OK || result == SAVE_RESULT_NG){
			(*seq) = 0;
			sys_SoftResetOK(SOFTRESET_TYPE_VIDEO);
      OS_Printf("通常セーブ終了\n");
		}
		return result;
	}
	return SAVE_RESULT_CONTINUE;
}

#endif  //AFTERMASTER_BTL_REC_FORCE_SVAE